#include "index.h"
#include "qtch/log.h"
#include "qtch/util.h"
#include <string.h>

namespace qtch {
namespace orm {

static Logger::ptr logger = QTCH_LOG_NAME("orm");

bool Index::init(const tinyxml2::XMLElement& node) {
    if(strcmp(node.Name(),"index") != 0){
        QTCH_LOG_ERROR(logger) << "parse error  it's not index node";
        return false;
    }
    if(!node.Attribute("name")){
        QTCH_LOG_ERROR(logger) << "index name not exists";
        return false;
    }
    m_name = node.Attribute("name");

    if(!node.Attribute("type")){
        QTCH_LOG_ERROR(logger) << "index name=" << m_name << " type is null";
        return false;
    }
    m_type = node.Attribute("type");
    m_dtype = ParseType(m_type);
    if(m_dtype == TYPE_NULL) {
        QTCH_LOG_ERROR(logger) << "index name=" << m_name << " type=" << m_type
                               << " invalid(pk,index,uniq)";
        return false;
    }
    if(!node.Attribute("cols")){
        QTCH_LOG_ERROR(logger) << "index name=" << m_name << " type=" << m_type
                               << " col is null";
        return false;
    }
    std::string tmp = node.Attribute("cols");
    m_cols = StringUtil::split(tmp, ',');
    if(node.Attribute("desc")){
        m_desc = node.Attribute("desc");
    }
    return true;
}

Index::Type Index::ParseType(const std::string& v) {
#define XX(a,b) \
    if(v == #b){ \
        return a; \
    }
    XX(TYPE_PK,pk);
    XX(TYPE_UNIQ,uniq);
    XX(TYPE_INDEX,index);
#undef XX
    return TYPE_NULL;
}

std::string Index::TypeToString(Type v) {
    switch(v){
#define XX(a,b) \
    case(a): \
        return #b;
    XX(TYPE_PK,pk);
    XX(TYPE_UNIQ,uniq);
    XX(TYPE_INDEX,index);
#undef XX
    default:
        return "";
    }
}

std::string Index::toString()const {
    std::stringstream ss;
    dump(ss);
    return ss.str();
}

std::ostream& Index::dump(std::ostream& os) const {
    os << "[index name=" << m_name << " type=" << m_type << " dtype=" << m_dtype
       << " desc=(";
    for(size_t i = 0; i < m_cols.size(); ++i) {
        if(i != 0){
            os << ", ";
        }
        os << m_cols[i];
    }
    os << ") ]";
    return os;
}

std::ostream& operator<<(std::ostream& os, const Index& index) {
    index.dump(os);
    return os;
}

std::ostream& operator<<(std::ostream& os, const Index::ptr index) {
    index->dump(os);
    return os;
}


}
}